import useToast from '@/hooks/useToast';
import { type ChangeEvent, type FormEvent, useEffect, useState } from 'react';
import type { TBody, TSectionOtherState, TSectionState } from '@/types';
import type {
  IDifference,
  ISectionDetails,
  IUpdateSectionStatusBody,
} from '@/interfaces';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { updateSectionStatus } from '@/services/api';
import diff from 'microdiff';
import {
  SECTION_OTHER_STATE_KEY,
  SECTION_OTHER_STATE_LIST,
  SECTION_STATE_KEY,
  SECTION_STATE_LIST,
  SECTION_STATE_OBJ,
} from '@/lib/constant';
import {
  getDiffData,
  getFilterData,
  getRandomIntInclusive,
  isEmpty,
  isNum,
} from '@/lib/tool';

export default function UpdateSectionState({
  details,
}: {
  details: ISectionDetails;
}) {
  const { show } = useToast();
  const [form, setForm] = useState<{
    state?: TSectionState;
    otherStates?: TSectionOtherState[];
    secret?: string;
    allow?: string[];
    block?: string[];
  }>({
    secret: '',
    otherStates: ['DEFAULT'],
    allow: [],
    block: [],
  });
  const [differenceData, setDifferenceData] = useState<IDifference[]>([]);
  const queryClient = useQueryClient();
  const [otherStateValue, setOtherStateValue] = useState([
    true,
    false,
    false,
    false,
  ]);

  const updateSectionStatusMutation = useMutation(
    async (variables: TBody<IUpdateSectionStatusBody>) => {
      await updateSectionStatus(variables);
      await queryClient.invalidateQueries([
        '/forum',
        '/sections',
        details.basic.id,
        '/details',
      ]);
    },
  );

  useEffect(() => {
    if (details) {
      const { basic } = details;
      const otherStates: TSectionOtherState[] =
        basic.otherStates.length === 0 ? ['DEFAULT'] : basic.otherStates;
      const tempOtherStateValue = [...otherStateValue];
      otherStates
        .map((item) => {
          return SECTION_OTHER_STATE_LIST.findIndex((value) => value === item);
        })
        .forEach((item) => {
          tempOtherStateValue[item] = true;
        });

      setForm({
        state: basic.state,
        otherStates,
        secret: '',
        allow: basic.allow ? basic.allow.map((item) => item + '') : [],
        block: basic.block ? basic.block.map((item) => item + '') : [],
      });
      setOtherStateValue(tempOtherStateValue);
    }
  }, [details]);
  useEffect(() => {
    if (details) {
      const { basic } = details;
      const otherStates: TSectionOtherState[] =
        basic.otherStates.length === 0 ? ['DEFAULT'] : basic.otherStates;
      const differences = diff(
        {
          state: basic.state,
          otherStates,
          secret: '',
          allow: basic.allow ? basic.allow.map((item) => item + '') : [],
          block: basic.block ? basic.block.map((item) => item + '') : [],
        },
        {
          state: form.state,
          otherStates: form.otherStates,
          secret: form.secret,
          allow: (form.allow || []).filter((item) => isNum(item)),
          block: (form.block || []).filter((item) => isNum(item)),
        },
      );
      setDifferenceData(differences);
    }
  }, [form, details]);

  function onChangeForm(
    e: ChangeEvent<HTMLSelectElement | HTMLInputElement | HTMLTextAreaElement>,
  ) {
    const name = e.target.name;
    const value = e.target.value;

    if (name === 'otherStates') {
      const index = SECTION_OTHER_STATE_LIST.findIndex(
        (item) => item === value,
      );
      const newOtherStateValue = [...otherStateValue];
      newOtherStateValue[index] = !newOtherStateValue[index];
      const otherStates = newOtherStateValue
        .map((item, index) => (item ? SECTION_OTHER_STATE_LIST[index] : ''))
        .filter((item) => item) as TSectionOtherState[];
      setOtherStateValue(newOtherStateValue);
      setForm({
        ...form,
        otherStates,
      });
    } else if (name === 'allow') {
      setForm({
        ...form,
        allow: value
          .replaceAll('，', ',')
          .split(',')
          .filter((item) => item),
      });
    } else if (name === 'block') {
      setForm({
        ...form,
        block: value
          .replaceAll('，', ',')
          .split(',')
          .filter((item) => item),
      });
    } else {
      setForm({ ...form, [name]: value });
    }
  }

  async function onClickSave(e: FormEvent<HTMLFormElement>) {
    try {
      e.preventDefault();
      e.stopPropagation();

      checkForm();
      const body = getFilterData(getDiffData(differenceData));
      handleDefaultData(body);

      if (body.allow) {
        body.allow = body.allow
          .filter((value: string) => isNum(value))
          .map((value: string) => parseInt(value));
      }
      if (body.block) {
        body.block = body.block
          .filter((value: string) => isNum(value))
          .map((value: string) => parseInt(value));
      }

      if (isEmpty(body)) {
        show({
          type: 'SUCCESS',
          message: '保存完成',
        });
        return;
      }

      await updateSectionStatusMutation.mutateAsync({
        id: details.basic.id,
        data: body as any,
      });

      clearData();
      show({
        type: 'SUCCESS',
        message: '保存完成',
      });
    } catch (e) {
      updateSectionStatusMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onClickRandomKey() {
    let secret = '';
    for (let i = 0; i < 4; i++) {
      secret += getRandomIntInclusive(0, 9) + '';
    }
    setForm({ ...form, secret });
  }

  function handleDefaultData(data: Record<string, any>) {
    const otherStates = form.otherStates || [];
    if (otherStates.includes('DEFAULT')) {
      data.otherStates = [];
      data.allow = [];
      data.block = [];
    }
  }

  function clearData() {
    setDifferenceData([]);
  }

  function checkForm() {
    const { otherStates = [], allow, block } = form;

    if (otherStates.includes('ALLOW')) {
      if (!allow || allow.length === 0) {
        throw '白名单用户列表不能为空';
      }

      if (allow.find((item) => !isNum(item))) {
        throw '请正确输入白名单用户 Id';
      }
    }

    if (otherStates.includes('BLOCK')) {
      if (!block || block.length === 0) {
        throw '黑名单用户列表不能为空';
      }

      if (block.find((item) => !isNum(item))) {
        throw '请正确输入黑名单用户 Id';
      }
    }
  }

  return (
    <div className="row">
      <div className="col">
        <form onSubmit={onClickSave} className="vstack gap-4">
          <div>
            <label className="form-label">状态</label>
            <select
              name="state"
              value={form.state}
              onChange={onChangeForm}
              className="form-select"
              aria-label="state"
              placeholder="请选择版块状态"
            >
              {SECTION_STATE_LIST.map((key) => {
                return (
                  <option key={key} value={key}>
                    {SECTION_STATE_KEY[key]}
                  </option>
                );
              })}
            </select>
          </div>

          {form.state === SECTION_STATE_OBJ.LOCK && (
            <div>
              <label className="form-label">密钥</label>
              <div className="input-group">
                <input
                  type="text"
                  className="form-control"
                  name="secret"
                  value={form.secret}
                  onChange={onChangeForm}
                  placeholder="请输入密钥（请注意保存，密钥只会显示一次，更新后密钥将不可见）"
                />
                <button
                  onClick={onClickRandomKey}
                  className="btn btn-outline-secondary"
                  type="button"
                >
                  随机生成
                </button>
              </div>
            </div>
          )}

          <div>
            <label className="form-label">其他状态</label>
            <div className="form-control">
              {SECTION_OTHER_STATE_LIST.map((key, index) => {
                return (
                  <div key={key} className="form-check form-check-inline">
                    <input
                      id={`yw-section-otherStates-${key}-${index}`}
                      aria-label="otherStates"
                      name="otherStates"
                      onChange={onChangeForm}
                      className="form-check-input"
                      type="checkbox"
                      value={key}
                      checked={otherStateValue[index]}
                      disabled={
                        ((form.otherStates || []).length > 0 &&
                          !form.otherStates?.includes('DEFAULT') &&
                          key === 'DEFAULT') ||
                        (form.otherStates?.includes('DEFAULT') &&
                          key !== 'DEFAULT')
                      }
                    />
                    <label
                      className="form-check-label user-select-none"
                      htmlFor={`yw-section-otherStates-${key}-${index}`}
                    >
                      {SECTION_OTHER_STATE_KEY[key]}
                    </label>
                  </div>
                );
              })}
            </div>
          </div>

          {form.otherStates?.includes('ALLOW') && (
            <div>
              <label className="form-label">白名单</label>
              <textarea
                rows={1}
                className="form-control"
                name="allow"
                value={(form.allow || []).join(',')}
                onChange={onChangeForm}
                placeholder="请输入白名单用户 Id，多个用户 Id 使用逗号分隔"
              />
            </div>
          )}

          {form.otherStates?.includes('BLOCK') && (
            <div>
              <label className="form-label">黑名单</label>
              <textarea
                rows={1}
                className="form-control"
                name="block"
                value={(form.block || []).join(',')}
                onChange={onChangeForm}
                placeholder="请输入黑名单用户 Id，多个用户 Id 使用逗号分隔"
              />
            </div>
          )}

          <button
            type="submit"
            disabled={updateSectionStatusMutation.isLoading}
            className="btn btn-success w-25 my-4"
          >
            {updateSectionStatusMutation.isLoading && (
              <span
                className="spinner-border spinner-border-sm me-2"
                role="status"
                aria-hidden="true"
              ></span>
            )}
            更新
          </button>
        </form>
      </div>
    </div>
  );
}
